package cn.yeyiu.sexyiu.service

import org.springframework.stereotype.Service
import java.io.File
import java.io.IOException
import java.io.OutputStream
import java.io.RandomAccessFile
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

@Service
class MediaService {

    private val BUFFER_SIZE = 1024 * 500 //500kB

    fun writeVideo(request: HttpServletRequest, response: HttpServletResponse, file: File) {
        //获取响应的输出流
        val outputStream: OutputStream?
        try {
            outputStream = response.outputStream
            //获取从哪个字节开始读取文件
            val rangeString = request.getHeader("Range") //bytes=xxx-
            //文件工具
            val targetFile = RandomAccessFile(file, "r")
            val fileLength = targetFile.length()
            var rangeStart: Long = 0
            var rangeEnd = fileLength - 1 //包含这一字节
            if (rangeString != null) { //range非空，particle请求
                /*
                 * 表示第二个500字节：bytes=500-999
                 * 表示最后500个字节：bytes=-500
                 * 表示500字节以后的范围：bytes=500-
                 * 第一个和最后一个字节：bytes=0-0,-1
                 * 同时指定几个范围：bytes=500-600,601-999
                 * 目前实现单范围请求！
                 */
                val range = rangeString.substring(6) // 400-600, -500 , 400-
                if (range[0] != '-') { //400-600, 400-
                    val startAndEnd = range.split("-").toTypedArray()
                    rangeStart = startAndEnd[0].toLong()
                    rangeEnd = if (startAndEnd.size == 1) {
                        fileLength - 1
                    } else {
                        startAndEnd[1].toLong()
                    }
                } else { //-500
                    val len = range.substring(1).toLong()
                    rangeEnd = fileLength - 1
                    rangeStart = rangeEnd - len + 1
                }
                if (rangeEnd >= fileLength) { // 请求超过文件大小的处理
                    rangeEnd = fileLength - 1
                }
                response.setHeader("Accept-Ranges", "bytes")
                response.setHeader("Content-Range", "bytes $rangeStart-$rangeEnd/$fileLength")
                //设置内容类型
                response.setHeader("Content-Type", "video/mp4")
                //设置此次相应返回的数据长度，支持多线程
                response.setHeader("Content-Length", (rangeEnd - rangeStart + 1).toString())
                //返回码需要为206，而不是200
                response.status = HttpServletResponse.SC_PARTIAL_CONTENT

            } else { //range空，请求下载
                //设置响应头，把文件名字设置好
                response.setHeader("Accept-Ranges", "bytes")
                response.setHeader(
                    "Content-Disposition", "attachment; filename=" +
                            URLEncoder.encode(file.name, StandardCharsets.UTF_8)
                )
                //设置文件长度,支持多线程
                response.setHeader("Content-Length", fileLength.toString())
                //解决编码问题
                response.setHeader("Content-Type", "video/mp4")
                response.status = HttpServletResponse.SC_OK
            }

            // 开始返回内容
            var dataSize = rangeEnd - rangeStart + 1
            var readBytes: Long // 读了的字节数
            //设定文件读取开始位置（以字节为单位）
            val cache = ByteArray(BUFFER_SIZE)
            targetFile.seek(rangeStart)
            while (dataSize > 0) {
                readBytes = if (dataSize < BUFFER_SIZE) dataSize else BUFFER_SIZE.toLong()
                readBytes = targetFile.read(cache, 0, readBytes.toInt()).toLong()
                outputStream.write(cache, 0, readBytes.toInt())
                dataSize -= readBytes
            }
            outputStream.close()
        } catch (e: IOException) {
            // System.out.println(e.getMessage());
        }
    }

    fun writeImg(response: HttpServletResponse, file: File) {
        response.contentType = "image/png"
        val os: OutputStream
        try {
            os = response.outputStream
            val imgCache = ByteArray(BUFFER_SIZE)
            val targetImg = RandomAccessFile(file, "r")
            var readBytes: Int // 读了的字节数
            while (targetImg.read(imgCache).also { readBytes = it } != -1) {
                os.write(imgCache, 0, readBytes)
            }
            os.flush()
            os.close()
        } catch (e: IOException) {
            println("文件错误：" + e.localizedMessage)
        }
    }
}